package com.lin.pay;

import com.google.gson.Gson;
import com.lin.common.constant.CustomerServiceConstant;
import com.lin.common.error.CustomRuntimeException;
import com.lin.common.error.ErrorCode;
import com.lin.common.utils.DateUtils;
import com.lin.config.SpringContextIniter;
import com.lin.dao.PayOrderMapper;
import com.lin.pay.ali.ALIPayConstant;
import com.lin.pay.paypal.PaypalConstant;
import com.lin.pay.paypal.v1.PaymentService;
import com.lin.pay.paypal.v1.vo.CreatePaymentDto;
import com.lin.pay.paypal.v1.vo.CreatePaymentReqVo;
import com.lin.pay.wx.WXPayConstant;
import com.lin.pay.wx.sdk.WXPay;
import com.lin.pay.wx.sdk.WXPayConfig;
import com.lin.pay.wx.sdk.WxPayConfigImpl;
import com.lin.pay.wx.service.WxService;
import com.lin.po.Orders;
import com.lin.po.PayOrder;
import com.lin.po.RefundOrder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Component
public class PayServiceImpl implements PayService {
    Logger log = LoggerFactory.getLogger(PayServiceImpl.class);
    @Autowired
    private PayOrderMapper payOrderMapper;

    private Gson g = new Gson();
    @Autowired
    private WxService wxService;

    @Autowired
    private PaymentService paymentService;

    @Override
    public Map unifiedOrder(String channel, String openid, BigDecimal trxAmt, String currency, Long orderNo, Long payOrderNo) throws CustomRuntimeException, UnsupportedEncodingException {
        if (StringUtils.equals(channel, WXPayConstant.WEIXIN)) {
            Map map = wxService.pay(openid, trxAmt, orderNo, payOrderNo);
            log.info("wechat res is： {}", map);
            PayOrder po = buildPayOrder(payOrderNo, orderNo, null, trxAmt);
            payOrderMapper.insert(po);
            map.put(CustomerServiceConstant.ORDER_NO, orderNo);
            return map;
        } else if (StringUtils.equals(channel, ALIPayConstant.ALI)) {

        } else if (StringUtils.equals(channel, PaypalConstant.PAYPAL)) {
            CreatePaymentReqVo reqMsg = buildReq(trxAmt, currency);
            String result = paymentService.createPayment(reqMsg);
            log.info("wechat res is： {}", result);
            CreatePaymentDto vo = g.fromJson(result, CreatePaymentDto.class);
            PayOrder po = buildPayOrder(payOrderNo, orderNo, vo.getId(), trxAmt);
            payOrderMapper.insert(po);
            Map<String, String> map = new HashMap<>();
            map.put("id", vo.getId());
            return map;
        } else {

        }

        return null;
    }

    private CreatePaymentReqVo buildReq(BigDecimal trxAmt, String currency) {
        CreatePaymentReqVo reqMsg = new CreatePaymentReqVo();
        reqMsg.setCurrency(currency);
        reqMsg.setIntent("sale");
        reqMsg.setName("Purchase member");
        reqMsg.setPrice(String.valueOf(trxAmt));
        reqMsg.setQuantity("1");
        reqMsg.setShipping("0");
        reqMsg.setTax("0");
        return reqMsg;
    }

    @Override
    public String channelNotify(Map<String, String> map) throws Exception {
        return null;
    }

    @Override
    public Map<String, String> refund(String channel,Map<String, String> reqData) throws Exception {
        if (StringUtils.equals(channel, WXPayConstant.WEIXIN)) {
            final WXPayConfig pc = SpringContextIniter.getBean(WxPayConfigImpl.class);
            WXPay pay = new WXPay(pc, false);
            Map<String, String> resData = pay.refund(reqData);
            return resData;
        } else if (StringUtils.equals(channel, PaypalConstant.PAYPAL)) {

        }

        return null;
    }

    /**
     * 支付订单构建.
     *
     * @param payOrderNo
     * @param orderNo
     * @param trxAmt
     * @return
     */
    private PayOrder buildPayOrder(Long payOrderNo, Long orderNo, String paypalId, BigDecimal trxAmt) {
        PayOrder o = new PayOrder();
        o.setPayOrderNo(payOrderNo);
        o.setTransactionId(paypalId);
        o.setTrxStatus(Orders.TRX_STATUS_NOTPAY);
        o.setTrxAmt(trxAmt);
        o.setPayType(WXPayConstant.WX_MICRO);
        o.setTradChnl(CustomerServiceConstant.TRAD_CHNL_WEIXIN);
        o.setBody(orderNo + "");
        o.setCreateTime(DateUtils.fullDateFormat());
        o.setUpdateTime(DateUtils.fullDateFormat());
        o.setInstDate(DateUtils.dateFormat());
        o.setInstTime(DateUtils.timeFormat());
        return o;
    }
    private RefundOrder buildRefund(PayOrder o, Long refundOrderNo, String refundId, BigDecimal refundAmt, String desc) {
        RefundOrder ro = new RefundOrder();
        ro.setPayOrderNo(o.getPayOrderNo());
        ro.setRefundNo(refundOrderNo);
        ro.setRefundId(refundId);
        ro.setTrxAmt(refundAmt);
        ro.setRefundDesc(desc);
        ro.setInstDate(DateUtils.dateFormat());
        ro.setInstTime(DateUtils.timeFormat());
        ro.setPayType(RefundOrder.PAY_TYPE);
        ro.setTradChnl(RefundOrder.TRAD_CHNL_WX);
        ro.setTrxStatus(RefundOrder.TRX_STATUS_SUCCESS);
        ro.setRefundTime(DateUtils.fullDateFormat());
        ro.setCreateTime(DateUtils.fullDateFormat());
        ro.setUpdateTime(DateUtils.fullDateFormat());
        return ro;
    }
}
